package com.yeskery.nut.scan.bean;

import com.yeskery.nut.annotation.bean.Bean;
import com.yeskery.nut.annotation.bean.Configuration;
import com.yeskery.nut.annotation.bean.Primary;
import com.yeskery.nut.bean.ApplicationContext;
import com.yeskery.nut.bean.FactoryBeanRegister;
import com.yeskery.nut.scan.AnnotationHandler;
import com.yeskery.nut.scan.BeanAnnotationScanMetadata;
import com.yeskery.nut.scan.BeanCreator;
import com.yeskery.nut.scan.ConfigurationBeanAnnotationScanMetadata;
import com.yeskery.nut.util.ReflectUtils;
import com.yeskery.nut.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Collection;

/**
 * 基于注解的Configuration扫描器
 * @author sprout
 * @version 1.0
 * 2022-07-09 19:21
 */
public class AnnotationConfigurationHandler implements AnnotationHandler {

    /** FactoryBean注解器 */
    private final FactoryBeanRegister factoryBeanRegister;

    /** 应用上下文 */
    private final ApplicationContext applicationContext;

    /** Bean创建接口 */
    private BeanCreator beanCreator;

    /**
     * 构建基于注解的Configuration扫描器
     * @param factoryBeanRegister FactoryBean注解器
     * @param applicationContext 应用上下文
     */
    public AnnotationConfigurationHandler(FactoryBeanRegister factoryBeanRegister, ApplicationContext applicationContext) {
        this.factoryBeanRegister = factoryBeanRegister;
        this.applicationContext = applicationContext;
    }


    @Override
    public void handle(Collection<Class<?>> beanClassCollection, Collection<BeanAnnotationScanMetadata> beanMetadataCollection) {
        if (beanCreator == null) {
            beanCreator = new ConfigurationBeanCreator(factoryBeanRegister, applicationContext, beanMetadataCollection);
        }
        for (Class<?> clazz : beanClassCollection) {
            ReflectUtils.getTargetByApplication(applicationContext, clazz);
            for (Method method : ReflectUtils.getBeanAnnotationMethod(clazz, Bean.class)) {
                Bean annotation = method.getAnnotation(Bean.class);
                String beanName = StringUtils.isEmpty(annotation.value()) ? method.getName() : annotation.value();
                ConfigurationBeanAnnotationScanMetadata beanAnnotationScanMetadata =
                        new ConfigurationBeanAnnotationScanMetadata(beanName, method.getReturnType(),
                                BeanAnnotationScanMetadata.Source.CONFIGURATION, method.isAnnotationPresent(Primary.class), Configuration.class,
                                null, clazz, method);
                beanCreator.createBean(beanAnnotationScanMetadata);
            }
        }
    }
}
